/** \file    profile/cmdline.h
  * \brief   Stores parsed command line and gives easy access to all the options.
  * \date    2003
  * \author  Fedor Chelnokov
  * \version $Header: /home/cscom1r4/cvsroot/cs/include/profile/cmdline.h,v 1.3 2004/02/11 17:47:39 cscom1r4 Exp $
  */

#ifndef _profile_cmdline_h_
#define _profile_cmdline_h_

#include <string>
#include <sstream>
#include <set>
#include <vector>

class cmdline {
public:
	typedef std::set<std::string> options_type;
	typedef std::vector<std::string> args_type;
public:
	options_type options;
	args_type args;
public:
	cmdline(int argc, const char ** argv)
		{ reset(argc, argv); }
	cmdline(int argc, char ** argv)
		{ reset(argc, const_cast<const char **>(argv)); }
	void reset(int argc, const char ** argv);

	bool has_options() const
		{ return !options.empty(); }

	bool has_option(const std::string & o) const;
	/// Returns suffix of first option starting with given prefix (e.g. "file=") or empty string,
	std::string option_suffix(const std::string & prefix) const;
	std::string option_suffix(const std::string & prefix, bool erase);

	enum status { ok, not_found, parse_error };

	/// Converts option's suffix into type of argument
	template <class T>
	status option_suffix(const std::string & prefix, T & suffix) const;
	template <class T>
	status option_suffix(const std::string & prefix, T & suffix, bool erase);

	/// Returns true if option was in the set before the call
	bool erase_option(const std::string & o);
	void erase_option_by_prefix(const std::string & prefix);
};

//templates

template <class T>
cmdline::status cmdline::option_suffix(const std::string & prefix, T & suffix) const
{
	options_type::const_iterator i = options.lower_bound(prefix);
	if (i == options.end() || i->compare(0, prefix.size(), prefix) != 0)
		return not_found;
	std::istringstream is(i->substr(prefix.size()));
	is >> suffix;
	if (is.fail())
		return parse_error;
	return ok;
}

template <class T>
cmdline::status cmdline::option_suffix(const std::string & prefix, T & suffix, bool erase)
{
	options_type::iterator i = options.lower_bound(prefix);
	if (i == options.end() || i->compare(0, prefix.size(), prefix) != 0)
		return not_found;
	std::istringstream is(i->substr(prefix.size()));
	if (erase)
		options.erase(i);
	is >> suffix;
	if (is.fail())
		return parse_error;
	return ok;
}

#endif //_profile_cmdline_h_
